/*
 * ============================================================================
 *
 *       Filename:  net.c
 *
 *    Description:  
 *
 *        Version:  1.0
 *        Created:  08/26/14 14:18:52
 *       Revision:  none
 *       Compiler:  gcc
 *
 *         Author:  jianxi sun (jianxi), ycsunjane@gmail.com
 *   Organization:  
 *
 * ============================================================================
 */
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>

#include "thread.h"
#include "common.h"
#include "dllayer.h"
#include "sockarr.h"
#include "message.h"
#include "netlayer.h"
#include "process.h"
#include "arg.h"

/* recv dllayer */
static int net_dllrecv(void *arg)
{
	struct message_t *msg;

	msg = safe_malloc(sizeof(struct message_t) +
		DLL_PKT_DATALEN);
	msg->data = (char *)msg + sizeof(struct message_t); 

	int rcvlen;
	rcvlen = dll_rcv(msg->data, DLL_PKT_DATALEN);
	if(rcvlen < (int)sizeof(struct ethhdr)) {
		free(msg);
		return -1;
	}
	msg->len = rcvlen;

	sys_info("datalink layer recive a packet\n");
	msg->proto = MSG_PROTO_ETH;
	message_insert(msg);
	return 0;
}

/* recv netlayer */
int net_netrcv(void *arg)
{
	struct sockarr_t *sockarr = arg;
	assert(sockarr == sysstat.sockarr);

	int clisock;
	unsigned int events;
	events = sockarr->bakevent;
	clisock = sockarr->sock;

	/*
	if(events & EPOLLRDHUP ||
		events & EPOLLERR ||
		!(events & EPOLLIN)) {
		debug_event(events);
		sys_debug("Epool get err: %s(%d)\n", 
			strerror(errno), errno);
		ac_lost();
		return -1;
	}
	*/

	sys_debug("net layer recive a packet\n");

	struct nettcp_t tcp;
	struct message_t *msg;
	msg = safe_malloc(sizeof(struct message_t));
	tcp.sock = clisock;
	if(tcp_rcv(&tcp, &msg->data, &msg->len) < 0) {
		ac_lost();
		free(msg);
		return -1;
	}
	msg->proto = MSG_PROTO_TCP;
	message_insert(msg);
	return 0;
}

static void sockarr_dllinit()
{
	int sock;
	/* init dll, add dllrcv in epoll */
	dll_init(&args_info.nic_arg[0], &sock, NULL, NULL);
	sockarr_insert(sock, net_dllrecv, NULL);
}

void net_init()
{
	/* init epoll */
	sockarr_init();

	sockarr_dllinit();

	/* create pthread recv msg */
	pthread_create_detach(sockarr_recv, NULL);
	sys_info("MODULE: net init success\n");
}

void net_restart()
{
	sockarr_clr();
	sys_info("clear all sockarr socket\n");
	dll_clr();
	sockarr_dllinit();
	sys_info("reinit dll sockarr socket\n");
}
